package com.optitronics.beans;

import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Version;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.transaction.annotation.Transactional;

import com.optitronics.util.OptitronicsConstants;

@Configurable
@Entity
@Table(name = "resellers")
public class Reseller {

	public static Integer STATUS_ACTIVE = Integer.valueOf(0);
	public static Integer STATUS_INACTIVE = Integer.valueOf(1);
	public static Integer STATUS_WAITING_FOR_ACTIVATION = Integer.valueOf(2);

	@PersistenceContext
	transient EntityManager entityManager;

	@Id
	@TableGenerator(name = "resellersGenerator", pkColumnValue = "RESELLERS", table = OptitronicsConstants.COUNTER_TABLE_NAME, pkColumnName = OptitronicsConstants.COUNTER_PK_COLUMN_NAME, valueColumnName = OptitronicsConstants.COUNTER_VALUE_COLUMN_NAME, allocationSize = OptitronicsConstants.COUNTER_ALLOCATION_SIZE)
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "resellersGenerator")
	@Column(name = "ID")
	private Integer id;

	@OneToMany(mappedBy = "reseller")
	private Set<ResellerOrder> resellerOrders;

	@Version
	@Column(name = "VERSION")
	private Integer version;

	@Column(name = "NAME")
	private String name;

	@Column(name = "TAX_NUMBER")
	private String taxNumber;

	@Column(name = "ACTIVATION_TOKEN")
	private String activationToken;

	@Column(name = "EMAIL")
	private String email;

	@Column(name = "PASSWORD")
	private String password;

	@Column(name = "STATUS")
	private Integer status;

	@Column(name = "PHONE_NUMBER")
	private String phoneNumber;

	@Column(name = "ADDRESS")
	private String address;

	@Column(name = "CITY")
	private String city;

	@Column(name = "CODE")
	private String code;

	public Set<ResellerOrder> getResellerOrders() {
		return this.resellerOrders;
	}

	public void setResellerOrders(Set<ResellerOrder> resellerOrders) {
		this.resellerOrders = resellerOrders;
	}

	public Integer getVersion() {
		return this.version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTaxNumber() {
		return this.taxNumber;
	}

	public void setTaxNumber(String taxNumber) {
		this.taxNumber = taxNumber;
	}

	public String getActivationToken() {
		return this.activationToken;
	}

	public void setActivationToken(String activationToken) {
		this.activationToken = activationToken;
	}

	public String getEmail() {
		return this.email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Integer getStatus() {
		return this.status;
	}

	public void setStatus(Integer status) {
		this.status = status;
	}

	public String getPhoneNumber() {
		return this.phoneNumber;
	}

	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Transactional
	public void persist() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.persist(this);
	}

	@Transactional
	public void flush() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.flush();
	}

	@Transactional
	public Reseller merge() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		Reseller merged = this.entityManager.merge(this);
		this.entityManager.flush();
		return merged;
	}

	public static final EntityManager entityManager() {
		EntityManager em = new Reseller().entityManager;
		if (em == null)
			throw new IllegalStateException(
					"Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
		return em;
	}

	public static long countResellers() {
		return entityManager().createQuery("select count(o) from Reseller o", Long.class).getSingleResult();
	}

	public static List<Reseller> findAllResellers() {
		return entityManager().createQuery("select o from Reseller o order by o.name", Reseller.class).getResultList();
	}

	public static Reseller findReseller(Integer id) {
		if (id == null)
			return null;
		return entityManager().find(Reseller.class, id);
	}

	public static List<Reseller> findResellerEntries(int firstResult, int maxResults) {
		return entityManager().createQuery("select o from Reseller o order by o.name", Reseller.class)
				.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
	}

	@SuppressWarnings("unchecked")
	public static Reseller findResellerByTaxNumber(String taxNumber) {
		String queryString = "SELECT r FROM Reseller r WHERE r.taxNumber = :taxNumber";
		List<Reseller> resultList = entityManager().createQuery(queryString).setParameter("taxNumber", taxNumber)
				.getResultList();
		return resultList.isEmpty() ? null : resultList.get(0);
	}

	@SuppressWarnings("unchecked")
	public static Reseller findResellerByEmail(String email) {
		String queryString = "SELECT r FROM Reseller r WHERE r.email = :email";
		List<Reseller> resultList = entityManager().createQuery(queryString).setParameter("email", email)
				.getResultList();
		return resultList.isEmpty() ? null : resultList.get(0);
	}

	@SuppressWarnings("unchecked")
	public static Reseller findResellerByEmailAndToken(String email, String token) {
		String queryString = "SELECT r FROM Reseller r WHERE r.email = :email AND r.activationToken = :activationToken";
		List<Reseller> resultList = entityManager().createQuery(queryString).setParameter("email", email)
				.setParameter("activationToken", token).getResultList();
		return resultList.isEmpty() ? null : resultList.get(0);
	}

	@SuppressWarnings("unchecked")
	public static Reseller findResellerByEmailAndTaxNumber(String email, String taxNumber) {
		String queryString = "SELECT r FROM Reseller r WHERE r.email = :email AND r.taxNumber = :taxNumber AND r.status = :status";
		Query query = entityManager().createQuery(queryString);
		query.setParameter("email", email);
		query.setParameter("taxNumber", taxNumber);
		query.setParameter("status", STATUS_ACTIVE);

		List<Reseller> resultList = query.getResultList();
		return resultList.isEmpty() ? null : resultList.get(0);
	}

	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("ResellerOrders: ").append(getResellerOrders() == null ? "null" : getResellerOrders().size())
				.append(", ");
		sb.append("Version: ").append(getVersion()).append(", ");
		sb.append("Name: ").append(getName()).append(", ");
		sb.append("TaxNumber: ").append(getTaxNumber()).append(", ");
		sb.append("ActivationToken: ").append(getActivationToken()).append(", ");
		sb.append("Email: ").append(getEmail()).append(", ");
		sb.append("Password: ").append(getPassword()).append(", ");
		sb.append("Status: ").append(getStatus()).append(", ");
		sb.append("PhoneNumber: ").append(getPhoneNumber()).append(", ");
		sb.append("Address: ").append(getAddress()).append(", ");
		sb.append("City: ").append(getCity()).append(", ");
		sb.append("Id: ").append(getId());
		return sb.toString();
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}
}
